#pragma once
#include<iostream>
#include<time.h>
#include<string.h>
#include<stdarg.h>
#include<errno.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 128
//设置日志等级
#define Info    0
#define Debug   1
#define Warning 2
#define Error   3
#define Fatal   4
//设置输出文件
#define Screen    1
#define Onefile   2
#define Manyfile 3

#define LogFile "log.txt"

using std::cout;
using std::endl;

class Log
{
public:
    Log()
    {
        _print_object=Screen;
        _path="./log/";
    }
    void change_print_into(int object)
    {
        _print_object=object;
    }
    void operator()(int level,const char* format,...)
    {
        time_t t=time(nullptr);
        struct tm* ctime=localtime(&t);

        //默认部分
        char front_buffer[SIZE];
        snprintf(front_buffer,sizeof(front_buffer),"[%s][%d-%d-%d:%d:%d:%d]",level_to_string(level).c_str(),\
        ctime->tm_year+1900,ctime->tm_mon+1,ctime->tm_mday,ctime->tm_hour,ctime->tm_min,ctime->tm_sec);
        //自定义部分
        va_list s;
        va_start(s,format);
        char back_buffer[SIZE];
        vsnprintf(back_buffer,sizeof(back_buffer),format,s);
        va_end(s);
        //格式：默认部分+自定义部分
        char logtxt[SIZE*2];
        snprintf(logtxt,sizeof(logtxt),"%s %s",front_buffer,back_buffer);

        //printf("%s\n",logtxt);
        print_log(level,logtxt);
    }
private:
    std::string level_to_string(int level)
    {
        switch(level)
        {
            case Info:return "Info";
            case Debug:return "Debug";
            case Warning:return "Warning";
            case Error:return "Error";
            case Fatal:return "Fatal";
            default:return "None";
        }
    }
    void print_log( int level,const std::string& logtxt)
    {
        switch(_print_object)
        {
            case Screen:
                cout<<logtxt<<endl;
            break;
            case Onefile:
                print_one_log(LogFile,logtxt);
            break;
            case Manyfile:
                print_many_log(level,logtxt);
            break;
            default:
            break;
        }
    }
    void print_one_log(const std::string& filename,const std::string& logtxt)
    {
        std::string path=_path+filename;
        int fd=open(path.c_str(),O_WRONLY | O_CREAT | O_APPEND,0666);//不同的日志信息都打印到同一个文件
        if(fd<0)return;
        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }
    void print_many_log(int level,const std::string& logtxt)
    {
        std::string filename=LogFile;
        filename+=".";
        filename+=level_to_string(level);//不同的日志信息打印到不同的文件，以后缀作区分，如log.txt.Debug、log.txt.Warning...
        print_one_log(filename,logtxt);
    }
private:
    int _print_object;
    std::string _path;
};

// int Sum(int n,...)
// {
//     va_list s;//本质是 char* 类型
//     va_start(s,n);//让s指向n“后面元素”的“起始地址”
//     int sum=0;

//     while(n)
//         sum+=va_arg(s,int),n--;//printf("hello %d,hello %c,hello %f",123,'c',3.14); %d、%c、%f控制参数类型
//     va_end(s);//将s置NULL
//     return sum;
// }
